package com.yy.cleaner.fliter;

import com.yy.cleaner.model.pojo.LoginUser;
import com.yy.cleaner.model.pojo.User;
import com.yy.cleaner.utils.JwtUtil;
import com.yy.cleaner.utils.RedisCache;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.PasswordAuthentication;
import java.util.Objects;

/**
 * token 认证过滤器
 * 用来解析和认证 请求转发过来的token
 * 这个过滤器应放置在 所有Security的拦截器 之前
 */
@Component
@Slf4j
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
    @Autowired
    private RedisCache redisCache;

    private String userId;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        //1.验证请求是否有合法的token
        String token = request.getHeader("token");
        //2.判断token是否存在于redis 若不存在 放行
        //即使放行 也是未认证的状态 后面的拦截器会将其过滤下来
        if(!StringUtils.hasText(token)){
            log.info("token为空 未获得认证");
            //放行
            filterChain.doFilter(request,response);
            return;
        }
        //3.若存在 解析token 将redis存储的用户信息取出 添加认证信息 放入 SecurityContextHolde
        //注意 SecurityContextHolder 只能在同一次请求中获得本次请求存储的对象
        try { //解析token
            Claims claims = JwtUtil.parseJWT(token);
            userId = claims.getSubject();
        } catch (Exception e) {
            throw new RuntimeException("token非法 解析失败");
        }
        //取出redis的信息
        User user = (User) redisCache.getCacheObject("loginUserId:" + userId);
        //判断 redis 信息是否存在
        if(Objects.isNull(user)){
            log.info("redis不存在用户信息 未获得认证");
            //放行
            filterChain.doFilter(request,response);
            return;
        }
        //存入security中
        //选择三个参数的构造器 理由：第三个参数表示授权
        //todo 添加授权信息
        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(user, null, null);
        SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
        //放行
        filterChain.doFilter(request,response);
    }
}
